package pl.asoft.nbp.model;

import org.hibernate.validator.constraints.NotEmpty;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

import java.math.BigDecimal;
import java.util.Date;

/**
 * Created by rbiedrawa on 2014-12-02.
 */

@NamedQueries({
        @NamedQuery(name = "ExchangeRate.findByShortName", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName"),
        @NamedQuery(name = "ExchangeRate.findByShortNameAndDate", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName AND e.dateOfPublication = :dateOfPublication"),
        @NamedQuery(name = "ExchangeRate.findByDate", query = "FROM ExchangeRate  e JOIN FETCH e.currency WHERE e.dateOfPublication = :dateOfPublication"),

        //FIXME: Simplify named queries (DRY/DIE). Create CRITERIA QUERY IN GENERIC DAO

        @NamedQuery(name = "ExchangeRate.withMaxPrice", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName and e.price = (SELECT MAX(price) FROM ExchangeRate er where er.currency.shortName = :shortName)"),
        @NamedQuery(name = "ExchangeRate.withMaxPriceAndDateBetween", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName and e.dateOfPublication between :startDate and :endDate and e.price  = (SELECT MAX(er.price) FROM ExchangeRate er where er.currency.shortName = :shortName and er.dateOfPublication between :startDate and :endDate) "),
        @NamedQuery(name = "ExchangeRate.withMaxPriceAndDateBetweenWithoutShortName", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.dateOfPublication between :startDate and :endDate and e.price  = (SELECT MAX(er.price) FROM ExchangeRate er where er.dateOfPublication between :startDate and :endDate) "),

        @NamedQuery(name = "ExchangeRate.findByShortNameOrderByPriceDESC", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName ORDER BY e.price DESC"),
        @NamedQuery(name = "ExchangeRate.findByShortNameOrderByPriceASC", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName ORDER BY e.price ASC"),

        @NamedQuery(name = "ExchangeRate.withMinPrice", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName and e.price = (SELECT MIN(price) FROM ExchangeRate er where er.currency.shortName = :shortName)"),
        @NamedQuery(name = "ExchangeRate.withMinPriceAndDateBetween", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName and e.dateOfPublication between :startDate and :endDate and e.price  = (SELECT MIN(er.price) FROM ExchangeRate er where er.currency.shortName = :shortName and er.dateOfPublication between :startDate and :endDate) "),

        @NamedQuery(name = "ExchangeRate.Average", query = "SELECT AVG(e.price) FROM ExchangeRate e WHERE e.currency.shortName = :shortName"),
        @NamedQuery(name = "ExchangeRate.AverageFromDates", query = "SELECT AVG(e.price) FROM ExchangeRate e WHERE e.currency.shortName = :shortName and e.dateOfPublication between :startDate and :endDate"),
        @NamedQuery(name = "ExchangeRate.aboveAverage", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName  and e.price > (SELECT AVG(er.price) FROM ExchangeRate er WHERE er.currency.shortName = :shortName  )"),
        @NamedQuery(name = "ExchangeRate.belowAverage", query = "FROM ExchangeRate e JOIN FETCH e.currency WHERE e.currency.shortName = :shortName and e.price < (SELECT AVG(er.price) FROM ExchangeRate er WHERE er.currency.shortName = :shortName )"),

})
@Entity
@Table(name = "NBP_KURSY")
public class ExchangeRate extends PersistentObject<Long> {
    @Id
    @GeneratedValue
    private Long id;
	
    @NotNull
    @Temporal(TemporalType.DATE)
    @Column(name = "DATA_PUBLIKACJI")
    private Date dateOfPublication;

    @Column(name = "KURS_SREDNI", columnDefinition = "Decimal(100,4) default '0.00'")
    private BigDecimal price;
    
    @ManyToOne
    private Currency currency;
    
    @Override
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }


    public Date getDateOfPublication() {
        return dateOfPublication;
    }

    public void setDateOfPublication(Date dateOfPublication) {
        this.dateOfPublication = dateOfPublication;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public BigDecimal getPriceAfterConversion() {
        return price.multiply(BigDecimal.valueOf(currency.getConversion()));
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }

    @Override
    public String toString() {
        return "ExchangeRate{" +
                "id=" + id +
                ", dateOfPublication=" + dateOfPublication +
                ", price=" + price +
                ", currency=" + currency +
                '}';
    }
}
